﻿//Created by Action Script Viewer - http://www.buraks.com/asv
package com.fminutes.vinciBitmap {
    import com.fminutes.vinciBase.*;
    
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.utils.*;

    public class BitmapProduced {
		/**
		 * 渲染的优先级
		 */
        public static const REAL_TIME:int = 1;//实时渲染
        public static const PREFERENTIAL:int = 2;
        public static const NORMAL:int = 3;

        public static var minFps:int = 10;//最小帧频
        public static var percentage:Number = 0.5;//百分比
        public static var appStage:Stage;//舞台
        private static var _instance:BitmapProduced;

        private var _compDic:Dictionary;
        private var _compFnDic:Dictionary;//渲染完成后回调方法容器
        private var _farmeCompFnDic:Dictionary;//渲染完一帧 回调方法容器
        private var _drawList:Array;//渲染列表
        private var _currentFrameDic:Dictionary;
        private var _priorityDic:Dictionary;//优先级 别容器
        private var _totalFramesDic:Dictionary;//总帧数容器
        private var _limitTime:int = 100;//每帧耗时
        private var _drawTime:int = 20;//压缩后的帧频
        private var _frameTime:int = 0;//当前时间

        public function BitmapProduced(){
            appStage = App.appStage;
            this._limitTime = (1000 / minFps);
            this._drawTime = ((1000 / appStage.frameRate) * percentage);
            this._frameTime = getTimer();
            this._compDic = new Dictionary();
            this._compFnDic = new Dictionary();
            this._farmeCompFnDic = new Dictionary();
            this._priorityDic = new Dictionary();
            this._drawList = [];
            this._currentFrameDic = new Dictionary();
            this._totalFramesDic = new Dictionary();
            appStage.addEventListener(Event.ENTER_FRAME, this.onEnterFrame);
        }
        private static function getInstance():BitmapProduced{
            if (_instance == null){
                _instance = new (BitmapProduced)();
            };
            return (_instance);
        }
		/**
		 * 画动画
		 * @param dobj 显示对象
		 * @param completeCallBack  画完回调
		 * @param completeAFrameCallBack 画完一帧回调
		 * @param random 渲染优先级
		 * 
		 */
        public static function draw(dobj:DisplayObject, completeCallBack:Function, completeAFrameCallBack:Function=null, random:int=3):void{
            var bp:BitmapProduced = getInstance();
            bp.draw(dobj, completeCallBack, completeAFrameCallBack, random);
        }

		/**
		 *侦听舞台事件 查看是否有渲染任务 
		 * @param _arg1
		 * 
		 */
        private function onEnterFrame(e:Event):void{
            this.drawHandler();
        }
		/**
		 *注册渲染对象 
		 * @param _arg1
		 * @param _arg2
		 * @param _arg3
		 * @param _arg4
		 * 
		 */
        private function draw(dobj:DisplayObject, completeCallBack:Function, completeAFrameCallBack:Function=null, random:int=3):void{
			//更具渲染优先级 添加显示对象到 渲染列表
            if (random == BitmapProduced.REAL_TIME){
                this._drawList.unshift(dobj);
            } else {
                if (random == BitmapProduced.PREFERENTIAL){
                    this._drawList.unshift(dobj);
                } else {
                  this._drawList.push(dobj);  
                };
            };
            this._compDic[dobj] = [];
            this._compFnDic[dobj] = completeCallBack;
            this._farmeCompFnDic[dobj] = completeAFrameCallBack;
            this._currentFrameDic[dobj] = 0;
            this._priorityDic[dobj] = random;
            this._totalFramesDic[dobj] = this.getSourceTotalFrames(dobj);
            this.gotoFrame(dobj, 0);
            this.drawHandler(true);
        }
		/**
		 *开始渲染 
		 * @param flag
		 * 
		 */
        private function drawHandler(flag:Boolean=false):void{
            var t:int;
            var temp:int;
            var randObj:DisplayObject;//要渲染的对象
			//渲染列表完成返回
            if (this._drawList.length == 0){
                return;
            };
            if (flag == false){
                t = getTimer();
				temp = (t - this._frameTime);
                this._frameTime = t;
                if (temp > this._limitTime){
                    return;
                };
            } else {
				randObj = this._drawList[0];
				//如果渲染的目标不是实时渲染优先级 返回
                if (this._priorityDic[randObj] != BitmapProduced.REAL_TIME){
                    return;
                };
            };
            this.allHandler();
        }
		/**
		 *渲染队列 
		 * 
		 */
        private function allHandler():void{
			var i:int;
			var len:int = this._drawList.length;
            var render:DisplayObject;
			var tFrame:int;
			var cFrame:int;
			var tempFrame:int;
			for(i=0; i<len; i++) {
				render = this._drawList[i];
				if (render == null){
					break;
				};
				tFrame = this._totalFramesDic[render];
				cFrame = this._currentFrameDic[render];
				for(tempFrame = cFrame; tempFrame<tFrame; tempFrame++) {
					this._compDic[render].push(this.drawMovieClip(render));
					this.gotoFrame(render, (tempFrame + 1));
					this._currentFrameDic[render] = (tempFrame + 1);
					if (tempFrame == 0){
						this.callFn(this._farmeCompFnDic[render], this._compDic[render], this._totalFramesDic[render]);
					};
					if (tempFrame == (tFrame - 1)){
						this._drawList[i] = null;
						this.callFn(this._compFnDic[render], this._compDic[render], this._totalFramesDic[render]);
					};
					if ((getTimer() - this._frameTime) > this._drawTime){
						return;
					};
					
				}
			}
			//从渲染队列中剔除 空对象
            while ((((this._drawList.length > 0)) && ((this._drawList[0] == null)))) {
                this._drawList.shift();
            };
        }
		/**
		 * 调用方法
		 * @param func
		 * @param value1
		 * @param value2
		 * 
		 */
        private function callFn(func:Function, value1:Object, value2:Object):void{
            func(value1, value2);
        }
		/**
		 *跳到某一帧 
		 * @param dobj
		 * @param frame
		 * 
		 */
        private function gotoFrame(dobj:DisplayObject, frame:int):void{
            var temp:int;
            if ((dobj is MovieClip)){
                if ((dobj as MovieClip).totalFrames > frame){
                    (dobj as MovieClip).gotoAndStop(frame);
                } else {
                    (dobj as MovieClip).gotoAndStop((dobj as MovieClip).totalFrames);
                };
            };
            if ((dobj is DisplayObjectContainer)){
				temp = 0;
                while (temp < (dobj as DisplayObjectContainer).numChildren) {
                    this.gotoFrame(DisplayObjectContainer(dobj).getChildAt(temp), frame);
					temp++;
                };
            };
        }
		/**
		 *获得原件中的最大的帧数 
		 * @param _arg1
		 * @return 
		 * 
		 */
        private function getSourceTotalFrames(dobj:DisplayObject):int{
            var i:int;
            var temp:int;//
            var totalFrame:int = 1;//最大帧数
			var mc:MovieClip = dobj as MovieClip;
            if (mc){
				totalFrame = mc.totalFrames;
            };
			var container:DisplayObjectContainer = dobj as DisplayObjectContainer;
            if (container){
                i = 0;
				var len:int = container.numChildren;
				for(i=0; i<len; i++) {
					temp = this.getSourceTotalFrames(container.getChildAt(i));
					if (temp > totalFrame){
						totalFrame = temp;
					};
					i++;
				}
            };
            return totalFrame;
        }
		/**
		 *要绘制的显示对象 
		 * @param dobj
		 * @return [绘制完的显示对象的位图数据, 显示对象的偏移坐标]
		 * 
		 */
		private function drawMovieClip(dobj:DisplayObject):Array{
			var r:Rectangle = dobj.getBounds(dobj);
			r.width = (r.width + 3);
			var bmd:BitmapData = new BitmapData(r.width, r.height, true, 0xFFFFFF);
			var matrix:Matrix = new Matrix(1, 0, 0, 1, -int(r.x), -int(r.y));
			bmd.draw(dobj, matrix);
			return ([bmd, new Point(int(r.x), int(r.y))]);
		}
    }
}
